package db_layer;

import java.sql.Connection;
import java.sql.SQLException;

import com.microsoft.sqlserver.jdbc.SQLServerDataSource;
import com.microsoft.sqlserver.jdbc.SQLServerException;

public class DBConnection
{
	private static DBConnection instance;
	private static Connection connection;
	/**
	 * This is a constructor of DBConnection class.
	 * It can only be accessed from within this class (note private in front of the name)
	 * It creates a connection with the database via DataSource which is in general perceived as a better solution than using DriverManagers.
	 * If you are interested why is that, see: http://docs.oracle.com/javase/tutorial/jdbc/basics/sqldatasources.html#datasource_connection
	 */
	private DBConnection()
	{
		SQLServerDataSource data_source = new SQLServerDataSource();
		data_source.setServerName("balder.ucn.dk");		//set the name of the server - it is not required since localhost is default one, it would be if it was Internet db
		data_source.setPortNumber(1433);			//set port number, also not required 1433 is default
		data_source.setSelectMethod("direct");		//also default, this specifies the way results will be sent from the db to the program, 
													//in this case it should be faster solution than using cursor
		data_source.setDatabaseName("dmaj0913_4");	//name of the db, nothing fancy here (required)
		data_source.setUser("dmaj0913_4");					//name of the user of the database	(required)
		data_source.setPassword("IsAllowed");		//user password	(required)
		try
		{
			connection = data_source.getConnection();	//here we try to create the connection
			System.out.println("Successfully_connected to database.");
		}
		catch( SQLServerException e)
		{
			System.out.println("Could not connect to the database: " + e);	//if something goes wrong and we fail miserably, at least we will be informed about it
		}

	}
	
	/**
	 * This method returns a singleton instance of DBConnection class - the only singleton class in the program.
	 * If the instance had not been initialised it creates a new object of DBConnection class.
	 */
	public static DBConnection get_instance()
	{
		if (instance == null)
		{
			instance = new DBConnection();
		}
		return instance;
	}
	
	/**
	 * This method returns a Connection.
	 * Since DBConnection is a singleton, it is always the same connection every time you launch this method.
	 */
	public Connection get_connection()
	{
		return connection;
	}
	
	/**
	 * This method begins a transaction. This means that all statements coming after this one will either all be successful, or none of them will.
	 * This makes sure that no inconsistencies will occur in the database due to partial failure of statements that are connected to each other.
	 * This method returns true if the transaction was successfully begun and false otherwise.
	 */
	public static boolean begin_transaction()
	{
		try
		{
			connection.setAutoCommit(false);
			return true;
		}
		catch(SQLException e)
		{
			System.err.println("An error occured while begining a transaction. " + e);
			return false;
		}
	}
	
	/**
	 * This method ends a transaction. This means all the statements that were executed between calling begin_transaction and this function
	 *  will now be committed and saved in the database. If commit fails, this method rollbacks the transaction.
	 */
	
	public static void end_transaction()
	{
		try
		{
			connection.setAutoCommit(true);
		}
		catch(SQLException e)
		{
			System.err.println("Error while committing transaction! " + e);
			rollback_transaction();
		}
	}
	
	public static void rollback_transaction()
	{
		try
		{
			System.err.println("Rolling back.");
			connection.rollback();
			connection.setAutoCommit(true);
		}
		catch(SQLException e)
		{
			System.err.println("Error while rolling back! " + e);
		}
	}

}
